<template>
  <div class="user-container">
    <el-card class="container-card" shadow="always">
      <el-form size="small" :inline="true" :model="params" class="demo-form-inline">
        <el-form-item label="用户名">
          <el-input v-model.trim="params.username" clearable placeholder="用户名" @clear="search" />
        </el-form-item>
        <el-form-item label="昵称">
          <el-input v-model.trim="params.nickname" clearable placeholder="昵称" @clear="search" />
        </el-form-item>
        <el-form-item label="状态">
          <el-select v-model.trim="params.status" clearable placeholder="状态" @change="search" @clear="search">
            <el-option label="正常" value="1" />
            <el-option label="禁用" value="2" />
          </el-select>
        </el-form-item>
        <el-form-item label="手机号">
          <el-input v-model.trim="params.mobile" clearable placeholder="手机号" @clear="search" />
        </el-form-item>
        <el-form-item>
          <el-button :loading="loading" :icon="Search" type="primary" @click="search">查询</el-button>
        </el-form-item>
        <el-form-item>
          <el-button :loading="loading" :icon="Plus" type="warning" @click="create">新增</el-button>
        </el-form-item>
        <el-form-item>
          <el-button :disabled="multipleSelection.length === 0" :loading="loading" :icon="Delete" type="danger" @click="batchDelete">批量删除</el-button>
        </el-form-item>
      </el-form>

      <el-table v-loading="loading" :data="tableData" border stripe style="width: 100%" @selection-change="handleSelectionChange">
        <el-table-column type="selection" width="55" align="center" />
        <el-table-column show-overflow-tooltip sortable prop="username" label="用户名" align="center" />
        <el-table-column show-overflow-tooltip sortable prop="nickName" label="昵称" align="center" />
        <el-table-column show-overflow-tooltip sortable prop="mobile" label="手机号" align="center" />
        <el-table-column show-overflow-tooltip sortable prop="status" label="状态" align="center">
          <template #default="{ row }">
            <el-tag size="small" :type="row.status === 1 ? 'success':'danger'" disable-transitions>{{ row.status === 1 ? '正常':'禁用' }}</el-tag>
          </template>
        </el-table-column>
        <el-table-column show-overflow-tooltip sortable prop="creator" label="创建人" align="center" />
        <el-table-column show-overflow-tooltip sortable prop="introduction" label="说明" align="center" />
        <el-table-column fixed="right" label="操作" align="center" width="180">
          <template #default="{ row }">
            <div class="operation-buttons">
              <el-tooltip content="编辑" effect="dark" placement="top">
                <el-button size="small" type="primary" @click="update(row)">
                  <el-icon><Edit /></el-icon>
                </el-button>
              </el-tooltip>
              <el-tooltip content="删除" effect="dark" placement="top">
                <el-popconfirm
                  title="确定删除吗？"
                  @confirm="singleDelete(row.ID)"
                >
                  <template #reference>
                    <el-button size="small" type="danger">
                      <el-icon><Delete /></el-icon>
                    </el-button>
                  </template>
                </el-popconfirm>
              </el-tooltip>
            </div>
          </template>
        </el-table-column>
      </el-table>

      <el-pagination
        v-model:current-page="params.pageNum"
        v-model:page-size="params.pageSize"
        :total="total"
        :page-sizes="[1, 5, 10, 30]"
        layout="total, prev, pager, next, sizes"
        background
        style="margin-top: 10px;float:right;margin-bottom: 10px;"
        @size-change="handleSizeChange"
        @current-change="handleCurrentChange"
      />

      <el-dialog v-model="dialogFormVisible" :title="dialogFormTitle" width="30%">
        <el-form ref="dialogFormRef" size="small" :model="dialogFormData" :rules="dialogFormRules" label-width="100px">
          <el-form-item label="用户名" prop="username">
            <el-input ref="passwordRef" v-model.trim="dialogFormData.username" placeholder="用户名" />
          </el-form-item>
          <el-form-item :label="dialogType === 'create' ? '新密码':'重置密码'" prop="password">
            <el-input v-model.trim="dialogFormData.password" autocomplete="off" :type="passwordType" :placeholder="dialogType === 'create' ? '新密码':'重置密码'" />
            <span class="show-pwd" @click="showPwd">
              <svg-icon :icon-class="passwordType === 'password' ? 'eye' : 'eye-open'" />
            </span>
          </el-form-item>
          <el-form-item label="角色" prop="roleIds">
            <el-select v-model.trim="dialogFormData.roleIds" multiple placeholder="请选择角色" style="width:100%">
              <el-option
                v-for="item in roles"
                :key="item.id"
                :label="item.name"
                :value="item.id"
              />
            </el-select>
          </el-form-item>
          <el-form-item label="状态" prop="status">
            <el-select v-model.trim="dialogFormData.status" placeholder="请选择状态" style="width:100%">
              <el-option label="正常" :value="1" />
              <el-option label="禁用" :value="2" />
            </el-select>
          </el-form-item>
          <el-form-item label="昵称" prop="nickname">
            <el-input v-model.trim="dialogFormData.nickname" placeholder="昵称" />
          </el-form-item>
          <el-form-item label="手机号" prop="mobile">
            <el-input v-model.trim="dialogFormData.mobile" placeholder="手机号" />
          </el-form-item>
          <el-form-item label="说明" prop="introduction">
            <el-input v-model.trim="dialogFormData.introduction" type="textarea" placeholder="说明" show-word-limit maxlength="100" />
          </el-form-item>
        </el-form>
        <template #footer>
          <div class="dialog-footer">
            <el-button size="small" @click="cancelForm()">取 消</el-button>
            <el-button size="small" :loading="submitLoading" type="primary" @click="submitForm()">确 定</el-button>
          </div>
        </template>
      </el-dialog>

    </el-card>
  </div>
</template>

<script setup lang="ts">
import { ref, reactive, onMounted } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import type { FormInstance, FormRules } from 'element-plus'
import JSEncrypt from 'jsencrypt'
import { getUsers, createUser, updateUserById, batchDeleteUserByIds } from '@/api/system/user'
import { getRoles } from '@/api/system/role'
import { Search, Plus, Delete, Edit } from '@element-plus/icons-vue'

interface UserInfo {
  ID: number
  username: string
  nickname: string
  avatar: string
  mobile: string
  introduction: string
  status: number
  roleIds: number[]
  [key: string]: any
}

interface UserListParams {
  pageNum: number
  pageSize: number
  username: string
  nickname: string
  mobile: string
  status: number
}

interface DialogFormData {
  id?: number
  username: string
  password: string
  nickname: string
  status: number
  mobile: string
  avatar: string
  introduction: string
  roleIds: number[]
}

const checkPhone = (rule: any, value: string, callback: any) => {
  if (!value) {
    return callback(new Error('手机号不能为空'))
  } else {
    const reg = /^1[3|4|5|7|8][0-9]\d{8}$/
    if (reg.test(value)) {
      callback()
    } else {
      return callback(new Error('请输入正确的手机号'))
    }
  }
}

// 查询参数
const params = reactive<UserListParams>({
  username: '',
  nickname: '',
  status: 0,
  mobile: '',
  pageNum: 1,
  pageSize: 10
})

// 表格数据
const tableData = ref<any[]>([])
const total = ref(0)
const loading = ref(false)
const multipleSelection = ref<any[]>([])

// 角色
const roles = ref<any[]>([])

const passwordType = ref('password')

const publicKey = `-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDbOYcY8HbDaNM9ooYXoc9s+R5o
R05ZL1BsVKadQBgOVH/kj7PQuD+ABEFVgB6rJNi287fRuZeZR+MCoG72H+AYsAhR
sEaB5SuI7gDEstXuTyjhx5bz0wUujbDK4VMgRfPO6MQo+A0c95OadDEvEQDG3KBQ
wLXapv+ZfsjG7NgdawIDAQAB
-----END PUBLIC KEY-----`

// dialog对话框
const submitLoading = ref(false)
const dialogFormTitle = ref('')
const dialogType = ref('')
const dialogFormVisible = ref(false)
const dialogFormRef = ref<FormInstance>()
const passwordRef = ref()

const dialogFormData = reactive<DialogFormData>({
  username: '',
  password: '',
  nickname: '',
  status: 1,
  mobile: '',
  avatar: '',
  introduction: '',
  roleIds: []
})

const dialogFormRules: FormRules = {
  username: [
    { required: true, message: '请输入用户名', trigger: 'blur' },
    { min: 2, max: 20, message: '长度在 2 到 20 个字符', trigger: 'blur' }
  ],
  password: [
    { required: false, message: '请输入密码', trigger: 'blur' },
    { min: 6, max: 30, message: '长度在 6 到 30 个字符', trigger: 'blur' }
  ],
  nickname: [
    { required: false, message: '请输入昵称', trigger: 'blur' },
    { min: 2, max: 20, message: '长度在 2 到 20 个字符', trigger: 'blur' }
  ],
  mobile: [
    { required: true, validator: checkPhone, trigger: 'blur' }
  ],
  status: [
    { required: true, message: '请选择状态', trigger: 'change' }
  ],
  introduction: [
    { required: false, message: '说明', trigger: 'blur' },
    { min: 0, max: 100, message: '长度在 0 到 100 个字符', trigger: 'blur' }
  ]
}

// 查询
const search = () => {
  params.pageNum = 1
  getTableData()
}

// 获取表格数据
const getTableData = async () => {
  loading.value = true
  try {
    const { data } = await getUsers(params)
    console.log('用户列表数据:', data)
    if (data && data.users) {
      tableData.value = data.users
      total.value = data.total
      console.log('表格数据:', tableData.value)
    } else {
      tableData.value = []
      total.value = 0
    }
  } catch (error) {
    console.error('获取用户列表失败:', error)
    ElMessage.error('获取用户列表失败')
  } finally {
    loading.value = false
  }
}

// 获取角色数据
const getRolesData = async () => {
  const res = await getRoles(null)
  roles.value = res.data.list
}

// 新增
const create = () => {
  dialogFormTitle.value = '新增用户'
  dialogType.value = 'create'
  dialogFormVisible.value = true
}

// 修改
const update = (row: UserInfo) => {
  dialogFormData.id = row.id
  dialogFormData.username = row.username
  dialogFormData.password = ''
  dialogFormData.nickname = row.nickname
  dialogFormData.status = row.status
  dialogFormData.mobile = row.mobile
  dialogFormData.introduction = row.introduction
  dialogFormData.roleIds = row.roleIds

  dialogFormTitle.value = '修改用户'
  dialogType.value = 'update'
  passwordType.value = 'password'
  dialogFormVisible.value = true
}

// 提交表单
const submitForm = async () => {
  if (!dialogFormRef.value) return
  
  await dialogFormRef.value.validate(async (valid: boolean) => {
    if (valid) {
      submitLoading.value = true

      const dialogFormDataCopy = { ...dialogFormData }
      if (dialogFormData.password !== '') {
        // 密码RSA加密处理
        const encryptor = new JSEncrypt()
        // 设置公钥
        encryptor.setPublicKey(publicKey)
        // 加密密码
        const encPassword = encryptor.encrypt(dialogFormData.password)
        if (encPassword) {
          dialogFormDataCopy.password = encPassword
        }
      }
      let msg = ''
      try {
        if (dialogType.value === 'create') {
          const { message } = await createUser(dialogFormDataCopy)
          msg = message
        } else if (dialogFormDataCopy.id) {
          const { message } = await updateUserById(dialogFormDataCopy.id, dialogFormDataCopy)
          msg = message
        }
      } finally {
        submitLoading.value = false
      }

      resetForm()
      getTableData()
      ElMessage({
        showClose: true,
        message: msg,
        type: 'success'
      })
    } else {
      ElMessage({
        showClose: true,
        message: '表单校验失败',
        type: 'error'
      })
    }
  })
}

// 取消表单
const cancelForm = () => {
  resetForm()
}

// 重置表单
const resetForm = () => {
  dialogFormVisible.value = false
  if (dialogFormRef.value) {
    dialogFormRef.value.resetFields()
  }
  Object.assign(dialogFormData, {
    username: '',
    password: '',
    nickname: '',
    status: 1,
    mobile: '',
    avatar: '',
    introduction: '',
    roleIds: []
  })
}

// 批量删除
const batchDelete = () => {
  ElMessageBox.confirm('此操作将永久删除, 是否继续?', '提示', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning'
  }).then(async () => {
    loading.value = true
    const ids = multipleSelection.value.map(x => x.id)
    let msg = ''
    try {
      const { message } = await batchDeleteUserByIds(ids)
      msg = message
    } finally {
      loading.value = false
    }

    getTableData()
    ElMessage({
      showClose: true,
      message: msg,
      type: 'success'
    })
  }).catch(() => {
    ElMessage({
      showClose: true,
      type: 'info',
      message: '已取消删除'
    })
  })
}

// 表格多选
const handleSelectionChange = (val: any[]) => {
  multipleSelection.value = val
}

// 单个删除
const singleDelete = async (id: number) => {
  loading.value = true
  let msg = ''
  try {
    const { message } = await batchDeleteUserByIds([id])
    msg = message
  } finally {
    loading.value = false
  }

  getTableData()
  ElMessage({
    showClose: true,
    message: msg,
    type: 'success'
  })
}

// 显示/隐藏密码
const showPwd = () => {
  passwordType.value = passwordType.value === 'password' ? '' : 'password'
}

// 分页
const handleSizeChange = (val: number) => {
  params.pageSize = val
  getTableData()
}

const handleCurrentChange = (val: number) => {
  params.pageNum = val
  getTableData()
}

// 在组件挂载时获取数据
onMounted(() => {
  getTableData()
  getRolesData()
})
</script>

<style lang="scss" scoped>
.user-container {
  padding: 20px;
  background-color: #f0f2f5;
  min-height: 100%;
}

.container-card {
  margin-bottom: 20px;
}

.show-pwd {
  position: absolute;
  right: 10px;
  top: 7px;
  font-size: 16px;
  color: #889aa4;
  cursor: pointer;
  user-select: none;
}

.dialog-footer {
  text-align: right;
}

.operation-buttons {
  display: flex;
  justify-content: center;
  gap: 8px;
}
</style>
